package problems;

import interfaces.EulerProblemInterface;

import java.util.LinkedList;
import java.util.List;

import utility.DivisibilityChecker;
import utility.ProblemSpecifics;

public class EulerProblem002 implements EulerProblemInterface {

	private ProblemSpecifics problemSpecifics;
	private static final int UPPER_BOUNDARY = 4000000;
	private List<Integer> evenFibonaccies;

	public EulerProblem002() {
		String problemStatement = "By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.";
		problemSpecifics = new ProblemSpecifics(problemStatement);
		evenFibonaccies = new LinkedList<Integer>();
	}

	public void solve() {
		fillFibonacciSequenceWithEvenValuesUpToLimit();
		addAllToResult(evenFibonaccies);
		markAsSolved();
	}

	private void fillFibonacciSequenceWithEvenValuesUpToLimit() {

		int fibBeforeLastFib = 0;
		int lastFib = 1;
		int currentFib = 0;
		evenFibonaccies.add(currentFib);

		while (notGreaterThanLimit(currentFib)) {
			currentFib = fibBeforeLastFib + lastFib;
			if (isEven(currentFib)) {
				evenFibonaccies.add(currentFib);
			}
			fibBeforeLastFib = lastFib;
			lastFib = currentFib;
		}
	}

	private boolean notGreaterThanLimit(int c) {
		return c <= UPPER_BOUNDARY;
	}

	private boolean isEven(int c) {
		return DivisibilityChecker.firstEvenlyDividesSecond(c, 2);
	}

	private void addAllToResult(List<Integer> evenFibonaccies) {
		for (Integer i : evenFibonaccies) {
			problemSpecifics.addToResult(i);
		}
	}

	private void markAsSolved() {
		problemSpecifics.markAsSolved();
	}

	public long reportResult() {
		return problemSpecifics.reportResult();
	}

	public String stateTheProblem() {
		return problemSpecifics.stateTheProblem();
	}

	public ProblemStatus reportStatus() {
		return new ProblemStatus(problemSpecifics.isSolved());
	}
}
